package com.cbgolf.oa.util;


import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;

import com.cbgolf.oa.app.App;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by qianxiaoai on 2016/7/7.
 */
public class PermissionUtils {

  private static final String TAG = PermissionUtils.class.getSimpleName();
  public static final int CODE_RECORD_AUDIO = 0;
  public static final int CODE_GET_ACCOUNTS = 1;
  public static final int CODE_READ_PHONE_STATE = 2;
  public static final int CODE_CALL_PHONE = 3;
  public static final int CODE_CAMERA = 4;
  public static final int CODE_ACCESS_FINE_LOCATION = 5;
  public static final int CODE_ACCESS_COARSE_LOCATION = 6;
  public static final int CODE_READ_EXTERNAL_STORAGE = 7;
  public static final int CODE_WRITE_EXTERNAL_STORAGE = 8;
  public static final int CODE_MULTI_PERMISSION = 100;


  public static final String PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
  public static final String PERMISSION_GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
  public static final String PERMISSION_READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
  public static final String PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE;
  public static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
  public static final String PERMISSION_ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
  public static final String PERMISSION_ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
  public static final String PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
  public static final String PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;


  public static final String ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
  public static final String ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
  public static final String WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
  public static final String READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
  public static final String READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
  public static final String ACCESS_NETWORK_STATE = Manifest.permission.ACCESS_NETWORK_STATE;
  public static final String ACCESS_WIFI_STATE = Manifest.permission.ACCESS_WIFI_STATE;
  public static final String CHANGE_WIFI_STATE = Manifest.permission.CHANGE_WIFI_STATE;
  public static final String INTERNET = Manifest.permission.INTERNET;
  public static final String ACCESS_LOCATION_EXTRA_COMMANDS = Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
  public static final String BLUETOOTH_ADMIN = Manifest.permission.BLUETOOTH_ADMIN;
  public static final String BLUETOOTH = Manifest.permission.BLUETOOTH;
  public static final String WRITE_SETTINGS = Manifest.permission.WRITE_SETTINGS;


  public static final String WRITE_CONTACTS = Manifest.permission.WRITE_CONTACTS;
  public static final String READ_CONTACTS = Manifest.permission.READ_CONTACTS;

  public static final String CALL_PHONE = Manifest.permission.CALL_PHONE;


  public static final String GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
  public static final String GET_TASKS = Manifest.permission.GET_TASKS;

  public static final String CAMERA = Manifest.permission.CAMERA;
  private static String WAKE_LOCK = Manifest.permission.WAKE_LOCK;

  public static final int REQUEST_LOCAION_PERMISSIONS = 1000;
  public static final int REQUEST_UPDATE_PERMISSIONS = 1001;
  public static final int REQUEST_CAMERA_PERMISSIONS = 1002;
  public static final int REQUEST_INSTALL_APK_PERMISSION = 1003;
  public static final int REQUEST_QR_CODE = 1004;



  private static final String[] requestPermissions = {
      PERMISSION_RECORD_AUDIO,
      PERMISSION_GET_ACCOUNTS,
      PERMISSION_READ_PHONE_STATE,
      PERMISSION_CALL_PHONE,
      PERMISSION_CAMERA,
      PERMISSION_ACCESS_FINE_LOCATION,
      PERMISSION_ACCESS_COARSE_LOCATION,
      PERMISSION_READ_EXTERNAL_STORAGE,
      PERMISSION_WRITE_EXTERNAL_STORAGE
  };
  private static final String[] locationPermissions = {
      ACCESS_COARSE_LOCATION,
      ACCESS_FINE_LOCATION,
      WRITE_EXTERNAL_STORAGE,
      READ_EXTERNAL_STORAGE,
      READ_PHONE_STATE,
      ACCESS_NETWORK_STATE,
      ACCESS_WIFI_STATE,
      CHANGE_WIFI_STATE,
      INTERNET,
//      WRITE_SETTINGS,
//      ACCESS_LOCATION_EXTRA_COMMANDS,
//            BLUETOOTH_ADMIN,
//            BLUETOOTH,
      WAKE_LOCK
  };
  private static final String[] mpaPermissions = {
      ACCESS_COARSE_LOCATION,
      ACCESS_FINE_LOCATION,
      WRITE_EXTERNAL_STORAGE,
      READ_EXTERNAL_STORAGE,
      READ_PHONE_STATE,
      ACCESS_NETWORK_STATE,
      ACCESS_WIFI_STATE,
      CHANGE_WIFI_STATE,
      INTERNET,
//      WRITE_SETTINGS,
//      ACCESS_LOCATION_EXTRA_COMMANDS,
//      BLUETOOTH_ADMIN,
//      BLUETOOTH,
      WAKE_LOCK
  };
  public static final String[] writeSettingPermission = {
      WRITE_SETTINGS
  };
  private static final String[] ContactsPermissions = {
//            WRITE_CONTACTS,
      READ_CONTACTS

  };
  private static final String[] callPhonePermissions = {
      CALL_PHONE

  };
  private static final String[] cameraPermissions = {
      CAMERA,
      WRITE_EXTERNAL_STORAGE,
      READ_EXTERNAL_STORAGE

  };
  private static final String[] sharePermissions = {
      GET_TASKS,
      WRITE_EXTERNAL_STORAGE,
      READ_EXTERNAL_STORAGE,
//            GET_ACCOUNTS

  };

  public static boolean hasAllSharePermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return true;
    }
    String permission;
    for (int i = 0; i < sharePermissions.length; i++) {
      try {
        permission = sharePermissions[i];
//                if (App.getContext().checkCallingOrSelfPermission(permission) !=
//                        PackageManager.PERMISSION_GRANTED) {
//                    return false;
//                }
        if (ContextCompat.checkSelfPermission(App.getContext(), permission)
            != PackageManager.PERMISSION_GRANTED) {
          return false;
        }
      } catch (Exception e) {

      }
    }
    return true;
  }

  public static List<String> getShareNeedPermission() {
    List<String> permissions = new ArrayList<>();
    String locationPermission;
    for (int i = 0; i < sharePermissions.length; i++) {
      try {
        locationPermission = sharePermissions[i];
//                if (App.getContext().checkCallingOrSelfPermission(locationPermission) !=
//                        PackageManager.PERMISSION_GRANTED) {
//                    permissions.add(locationPermission);
//                }
        if (ContextCompat.checkSelfPermission(App.getContext(), locationPermission)
            != PackageManager.PERMISSION_GRANTED) {
          permissions.add(locationPermission);
        }
      } catch (Exception e) {

      }
    }
    return permissions;
  }

  public static List<String> getSharePermissionNames() {
    List<String> list = getShareNeedPermission();
    List<String> listNames = new ArrayList<>();
    if (null != list && list.size() > 0) {
      for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals(GET_ACCOUNTS)) {
          if (!listNames.contains("应用账户权限")) {
            listNames.add("应用账户权限");
          }
        } else if (list.get(i).equals(WRITE_EXTERNAL_STORAGE)
            || list.get(i).equals(READ_EXTERNAL_STORAGE)
            || list.get(i).equals(GET_TASKS)) {
          if (!listNames.contains("存储空间权限")) {
            listNames.add("存储空间权限");
          }

        }
      }
    }
    return listNames;
  }

  public static List<String> getLocationNeedPermission() {
    List<String> permissions = new ArrayList<>();
    String locationPermission;
    for (int i = 0; i < locationPermissions.length; i++) {
      try {
        locationPermission = locationPermissions[i];
//                if (App.getContext().checkCallingOrSelfPermission(locationPermission) !=
//                        PackageManager.PERMISSION_GRANTED) {
//                    permissions.add(locationPermission);
//                }
        if (ContextCompat.checkSelfPermission(App.getContext(), locationPermission)
            != PackageManager.PERMISSION_GRANTED) {
          permissions.add(locationPermission);
        }
      } catch (Exception e) {

      }
    }
    return permissions;
  }

  public static List<String> getContactsNeedPermission() {
    List<String> permissions = new ArrayList<>();
    String locationPermission;
    for (int i = 0; i < ContactsPermissions.length; i++) {
      try {
        locationPermission = ContactsPermissions[i];
//                if (App.getContext().checkCallingOrSelfPermission(locationPermission) !=
//                        PackageManager.PERMISSION_GRANTED) {
//                    permissions.add(locationPermission);
//                }
        if (ContextCompat.checkSelfPermission(App.getContext(), locationPermission)
            != PackageManager.PERMISSION_GRANTED) {
          permissions.add(locationPermission);
        }
      } catch (Exception e) {

      }
    }
    return permissions;
  }

  public static List<String> getContactsPermissionNames() {
    List<String> list = getContactsNeedPermission();
    List<String> listNames = new ArrayList<>();
    if (null != list && list.size() > 0) {
      listNames.add("读取通讯录权限");
    }
    return listNames;
  }

  public static List<String> getCameraPermissionNames() {
    List<String> list = getCameraNeedPermission();
    List<String> listNames = new ArrayList<>();
    if (null != list && list.size() > 0) {
      for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals(CAMERA)) {
          if (!listNames.contains("摄相头权限")) {
            listNames.add("摄相头权限");
          }
        } else {
          if (!listNames.contains("存储空间权限")) {
            listNames.add("存储空间权限");
          }
        }
      }
    }
    return listNames;
  }

  public static List<String> getCameraNeedPermission() {
    List<String> permissions = new ArrayList<>();
    String locationPermission;
    for (int i = 0; i < cameraPermissions.length; i++) {
      try {
        locationPermission = cameraPermissions[i];
//                if (App.getContext().checkCallingOrSelfPermission(locationPermission) !=
//                        PackageManager.PERMISSION_GRANTED) {
//                    permissions.add(locationPermission);
//                }
        if (ContextCompat.checkSelfPermission(App.getContext(), locationPermission)
            != PackageManager.PERMISSION_GRANTED) {
          permissions.add(locationPermission);
        }
      } catch (Exception e) {

      }
    }
    return permissions;

  }

  public static List<String> getLocationPermissionNames() {
    List<String> list = getLocationNeedPermission();
    List<String> listNames = new ArrayList<>();
    if (null != list && list.size() > 0) {
      for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals(ACCESS_COARSE_LOCATION)
            || list.get(i).equals(ACCESS_FINE_LOCATION)
            || list.get(i).equals(ACCESS_LOCATION_EXTRA_COMMANDS)
            ) {
          if (!listNames.contains("位置信息权限")) {
            listNames.add("位置信息权限");
          }
        } else if (list.get(i).equals(WRITE_EXTERNAL_STORAGE)
            || list.get(i).equals(READ_EXTERNAL_STORAGE)) {
          if (!listNames.contains("存储空间权限")) {
            listNames.add("存储空间权限");
          }
        } else if (list.get(i).equals(READ_PHONE_STATE)) {
          if (!listNames.contains("手机状态权限")) {
            listNames.add("手机状态权限");
          }
        } else if (list.get(i).equals(ACCESS_NETWORK_STATE)
            || list.get(i).equals(ACCESS_WIFI_STATE)
            || list.get(i).equals(CHANGE_WIFI_STATE)
            || list.get(i).equals(INTERNET)
            ) {
          if (!listNames.contains("网络及网络状态权限")) {
            listNames.add("网络及网络状态权限");
          }
        } else if (list.get(i).equals(BLUETOOTH_ADMIN)
            || list.get(i).equals(BLUETOOTH)) {
          if (!listNames.contains("蓝牙信息权限")) {
            listNames.add("蓝牙信息权限");
          }
        }

      }
    }
    return listNames;
  }

  public static boolean hasAllCameraPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return true;
    }
    String permission;
    for (int i = 0; i < cameraPermissions.length; i++) {
      try {
        permission = cameraPermissions[i];
//                if (App.getContext().checkCallingOrSelfPermission(permission) !=
//                        PackageManager.PERMISSION_GRANTED) {
//                    return false;
//                }
        if (ContextCompat.checkSelfPermission(App.getContext(), permission)
            != PackageManager.PERMISSION_GRANTED) {
          return false;
        }
      } catch (Exception e) {

      }
    }
    return true;
  }

  public static boolean hasWriteSettingPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return true;
    }
    String permission;
    for (int i = 0; i < writeSettingPermission.length; i++) {
      try {
        permission = writeSettingPermission[i];
        if (ContextCompat.checkSelfPermission(App.getContext(), permission)
            != PackageManager.PERMISSION_GRANTED) {
          return false;
        }
      } catch (Exception e) {

      }
    }
    return true;
  }

  public static List<String> getWriteSettingPermissionNames() {
    List<String> listNames = new ArrayList<>();
    listNames.add("数据权限");
    return listNames;
  }

  public static boolean hasAllContactsPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return true;
    }
    String permission;
    for (int i = 0; i < ContactsPermissions.length; i++) {
      try {
        permission = ContactsPermissions[i];
//                if (App.getContext().checkCallingOrSelfPermission(permission)
//                        != PackageManager.PERMISSION_GRANTED) {
//                    return false;
//                }
        if (ContextCompat.checkSelfPermission(App.getContext(), permission)
            != PackageManager.PERMISSION_GRANTED) {
          return false;
        }
      } catch (Exception e) {

      }
    }
    return true;
  }

  public static boolean hasCallPhonePermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return true;
    }
    String permission;
    for (int i = 0; i < callPhonePermissions.length; i++) {
      try {
        permission = callPhonePermissions[i];
        if (ContextCompat.checkSelfPermission(App.getContext(), permission)
            != PackageManager.PERMISSION_GRANTED) {
          return false;
        }
      } catch (Exception e) {

      }
    }
    return true;
  }

  public static boolean hasAllMapPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      String permission;
      for (int i = 0; i < mpaPermissions.length; i++) {
        try {
          permission = mpaPermissions[i];
          if (ContextCompat.checkSelfPermission(App.getContext(), permission)
              != PackageManager.PERMISSION_GRANTED) {
            return false;
          }
        } catch (Exception e) {
        }
      }
    }
    return true;
  }

  public static boolean hasAllLocationPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return true;
    }
    String permission = "";
    for (int i = 0; i < locationPermissions.length; i++) {
      try {
        permission = locationPermissions[i];
        if (ContextCompat.checkSelfPermission(App.getContext(), permission)
            != PackageManager.PERMISSION_GRANTED) {
          Log.e("permission------------", locationPermissions[i] + "------");
          return false;
        }
      } catch (Exception e) {
        Log.e("permission----catch----", locationPermissions[i] + "------" + e.toString());
        Log.e("location_permission:", e.toString() + "");
      }
    }
    return true;
  }

  public static boolean hasPermission(int requestCode) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return true;
    }
    if (requestCode < 0 || requestCode >= requestPermissions.length) {
      return true;
    }
    final String requestPermission = requestPermissions[requestCode];
    int checkSelfPermission;
    try {
      checkSelfPermission = ActivityCompat.checkSelfPermission(App.getContext(), requestPermission);
    } catch (RuntimeException e) {
      return false;
    }
    return checkSelfPermission == PackageManager.PERMISSION_GRANTED;
  }


  public static void requestPermission(Activity activity, int requestCode) {
    if (requestCode < 0 || requestCode >= requestPermissions.length) {
      return;
    }
    final String requestPermission = requestPermissions[requestCode];
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      return;
    }
    int checkSelfPermission;
    try {
      checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
    } catch (RuntimeException e) {
      Util.show("请打开此权限");
      Log.e(TAG, "RuntimeException:" + e.getMessage());
      return;
    }

    if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
      if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
        shouldShowRationale(activity, requestCode, requestPermission);
      } else {
        ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode);
      }
    }
  }


  interface PermissionGrant {

    void onPermissionGranted(int requestCode);
  }

  /**
   * Requests permission.
   *
   * @param requestCode request code, e.g. if you need request CAMERA permission,parameters is
   * PermissionUtils.CODE_CAMERA
   */
  public static void requestPermission(final Activity activity, final int requestCode,
      PermissionGrant permissionGrant) {
    if (activity == null) {
      return;
    }

    Log.i(TAG, "requestPermission requestCode:" + requestCode);
    if (requestCode < 0 || requestCode >= requestPermissions.length) {
      Log.w(TAG, "requestPermission illegal requestCode:" + requestCode);
      return;
    }

    final String requestPermission = requestPermissions[requestCode];

    //如果是6.0以下的手机，ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED，
    // 但是，如果用户关闭了你申请的权限，ActivityCompat.checkSelfPermission(),会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null)，
    // 你可以使用try{}catch(){},处理异常，也可以在这个地方，低于23就什么都不做，
    // 个人建议try{}catch(){}单独处理，提示用户开启权限。
//        if (Build.VERSION.SDK_INT < 23) {
//            return;
//        }

    int checkSelfPermission;
    try {
      checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
    } catch (RuntimeException e) {
      Toast.makeText(activity, "please open this permission", Toast.LENGTH_SHORT)
          .show();
      Log.e(TAG, "RuntimeException:" + e.getMessage());
      return;
    }

    if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
      Log.i(TAG, "ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED");

      if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
        Log.i(TAG, "requestPermission shouldShowRequestPermissionRationale");
        shouldShowRationale(activity, requestCode, requestPermission);

      } else {
        Log.d(TAG, "requestCameraPermission else");
        ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode);
      }

    } else {
      Log.d(TAG, "ActivityCompat.checkSelfPermission ==== PackageManager.PERMISSION_GRANTED");
      Toast.makeText(activity, "opened:" + requestPermissions[requestCode], Toast.LENGTH_SHORT)
          .show();
      permissionGrant.onPermissionGranted(requestCode);
    }
  }

  private static void requestMultiResult(Activity activity, String[] permissions,
      int[] grantResults, PermissionGrant permissionGrant) {

    if (activity == null) {
      return;
    }

    //TODO
    Log.d(TAG, "onRequestPermissionsResult permissions length:" + permissions.length);
    Map<String, Integer> perms = new HashMap<>();

    ArrayList<String> notGranted = new ArrayList<>();
    for (int i = 0; i < permissions.length; i++) {
      Log.d(TAG, "permissions: [i]:" + i + ", permissions[i]" + permissions[i] + ",grantResults[i]:"
          + grantResults[i]);
      perms.put(permissions[i], grantResults[i]);
      if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
        notGranted.add(permissions[i]);
      }
    }

    if (notGranted.size() == 0) {
      Toast.makeText(activity, "all permission success" + notGranted, Toast.LENGTH_SHORT)
          .show();
      permissionGrant.onPermissionGranted(CODE_MULTI_PERMISSION);
    } else {
      openSettingActivity(activity, "those permission need granted!");
    }

  }


  /**
   * 一次申请多个权限
   */
  public static void requestMultiPermissions(final Activity activity, PermissionGrant grant) {

    final List<String> permissionsList = getNoGrantedPermission(activity, false);
    final List<String> shouldRationalePermissionsList = getNoGrantedPermission(activity, true);

    //TODO checkSelfPermission
    if (permissionsList == null || shouldRationalePermissionsList == null) {
      return;
    }
    Log.d(TAG, "requestMultiPermissions permissionsList:" + permissionsList.size()
        + ",shouldRationalePermissionsList:" + shouldRationalePermissionsList.size());

    if (permissionsList.size() > 0) {
      ActivityCompat
          .requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]),
              CODE_MULTI_PERMISSION);
      Log.d(TAG, "showMessageOKCancel requestPermissions");

    } else if (shouldRationalePermissionsList.size() > 0) {
      showMessageOKCancel(activity, "should open those permission",
          new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
              ActivityCompat.requestPermissions(activity,
                  shouldRationalePermissionsList
                      .toArray(new String[shouldRationalePermissionsList.size()]),
                  CODE_MULTI_PERMISSION);
              Log.d(TAG, "showMessageOKCancel requestPermissions");
            }
          });
    } else {
      grant.onPermissionGranted(CODE_MULTI_PERMISSION);
    }

  }


  private static void shouldShowRationale(final Activity activity, final int requestCode,
      final String requestPermission) {
    //TODO
//        String[] permissionsHint = activity.getResources().getStringArray(permissions);
    String[] permissionsHint = new String[]{""};
    showMessageOKCancel(activity, "Rationale: " + permissionsHint[requestCode],
        new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            ActivityCompat.requestPermissions(activity,
                new String[]{requestPermission},
                requestCode);
            Log.d(TAG, "showMessageOKCancel requestPermissions:" + requestPermission);
          }
        });
  }

  private static void showMessageOKCancel(final Activity context, String message,
      DialogInterface.OnClickListener okListener) {
    new AlertDialog.Builder(context)
        .setMessage(message)
        .setPositiveButton("OK", okListener)
        .setNegativeButton("Cancel", null)
        .create()
        .show();

  }

  /**
   * @param requestCode Need consistent with requestPermission
   */
  public static void requestPermissionsResult(final Activity activity, final int requestCode,
      @NonNull String[] permissions,
      @NonNull int[] grantResults, PermissionGrant permissionGrant) {

    if (activity == null) {
      return;
    }
    Log.d(TAG, "requestPermissionsResult requestCode:" + requestCode);

    if (requestCode == CODE_MULTI_PERMISSION) {
      requestMultiResult(activity, permissions, grantResults, permissionGrant);
      return;
    }

    if (requestCode < 0 || requestCode >= requestPermissions.length) {
      Log.w(TAG, "requestPermissionsResult illegal requestCode:" + requestCode);
      Toast.makeText(activity, "illegal requestCode:" + requestCode, Toast.LENGTH_SHORT).show();
      return;
    }

    Log.i(TAG,
        "onRequestPermissionsResult requestCode:" + requestCode + ",permissions:" + permissions
            .toString()
            + ",grantResults:" + grantResults.toString() + ",length:" + grantResults.length);

    if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
      Log.i(TAG, "onRequestPermissionsResult PERMISSION_GRANTED");
      //TODO success, do something, can use callback
      permissionGrant.onPermissionGranted(requestCode);

    } else {
      //TODO hint user this permission function
      Log.i(TAG, "onRequestPermissionsResult PERMISSION NOT GRANTED");
      //TODO
//            String[] permissionsHint = activity.getResources().getStringArray(permissions);
//            openSettingActivity(activity, "Result" + permissionsHint[requestCode]);
    }

  }

  private static void openSettingActivity(final Activity activity, String message) {

    showMessageOKCancel(activity, message, new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Log.d(TAG, "getPackageName(): " + activity.getPackageName());
        Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
        intent.setData(uri);
        activity.startActivity(intent);
      }
    });
  }


  /**
   * @param isShouldRationale true: return no granted and shouldShowRequestPermissionRationale
   * permissions, false:return no granted and !shouldShowRequestPermissionRationale
   */
  public static ArrayList<String> getNoGrantedPermission(Activity activity,
      boolean isShouldRationale) {

    ArrayList<String> permissions = new ArrayList<>();

    for (int i = 0; i < requestPermissions.length; i++) {
      String requestPermission = requestPermissions[i];

      //TODO checkSelfPermission
      int checkSelfPermission = -1;
      try {
        checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
      } catch (RuntimeException e) {
        Toast.makeText(activity, "please open those permission", Toast.LENGTH_SHORT)
            .show();
        Log.e(TAG, "RuntimeException:" + e.getMessage());
        return null;
      }

      if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
        Log.i(TAG,
            "getNoGrantedPermission ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED:"
                + requestPermission);

        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
          Log.d(TAG, "shouldShowRequestPermissionRationale if");
          if (isShouldRationale) {
            permissions.add(requestPermission);
          }

        } else {

          if (!isShouldRationale) {
            permissions.add(requestPermission);
          }
          Log.d(TAG, "shouldShowRequestPermissionRationale else");
        }

      }
    }

    return permissions;
  }
}
